package com.ryder.club.gateway.filter;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 描述: 登录拦截器（过滤器）
 *
 * @author Ryder
 * @version 1.0
 * @since 1.0 // 版本号，指明从哪个版本开始
 * 更新日期: 2025/03/05
 */
// 声明为Spring组件，由Spring容器管理
@Component
// 使用Lombok的@Slf4j注解自动生成日志对象
@Slf4j
public class LoginFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取当前请求对象
        ServerHttpRequest request = exchange.getRequest();
        // 创建请求构建器用于修改请求（如添加请求头）
        ServerHttpRequest.Builder mutate = request.mutate();

        // 获取请求路径用于逻辑判断
        String url = request.getURI().getPath();
        log.info("LoginFilter.filter.url:{}", url);  // 打印请求路径日志

        // 放行登录接口（存在问题：此处未返回会导致后续逻辑继续执行）
        if (url.equals("/user/doLogin")) {
            // ❗问题：此处直接调用chain.filter()但未返回，会导致继续执行下方代码
            // 正确写法应返回 chain.filter(exchange)
            return chain.filter(exchange);
        }

        // 使用Sa-Token工具类获取当前Token信息
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        // 从Token中提取登录ID（需确保Sa-Token已正确配置）
        String loginId = (String) tokenInfo.getLoginId();

        // 检查登录ID是否为空
        if (StringUtils.isEmpty(loginId)) {
            // ❗问题：直接抛出异常可能导致不友好的错误响应，建议返回401状态码
            throw new RuntimeException("未获取到用户信息");
        }

        // 将登录ID添加到请求头供下游服务使用
        mutate.header("loginId", loginId);

        // 构建修改后的请求并继续过滤器链
        return chain.filter(
                exchange.mutate()
                        .request(mutate.build())
                        .build()
        );
    }
}